iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0
  • 重新調整從 Grind 75 開始,主要還是用 kotlin, 不過因未來會用到 java, python 所以也來複習一下吧。

1.Two Sum

  • Array/HashMap, Easy
  • introduction
    • 給定整數陣列 nums 和整數目標值 target,請返回兩個索引,使它們的數字和為 target。假設每個輸入只有一組解,且不能使用同一元素兩次。
  • solution
    • 用 HashMap 存儲數字與索引,一邊遍歷一邊檢查 target - nums[i] 是否已出現。
    • 時間:O(n)
    • 空間:O(n)
  • kotlin
fun twoSum(nums: IntArray, target: Int): IntArray {
    val map = mutableMapOf<Int, Int>()
    for ((i, num) in nums.withIndex()) {
        val complement = target - num
        if (map.containsKey(complement)) {
            return intArrayOf(map[complement]!!, i)
        }
        map[num] = i
    }
    return intArrayOf()
}
  • java
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[]{map.get(complement), i};
        }
        map.put(nums[i], i);
    }
    return new int[0];
}
  • python
def twoSum(nums, target):
    num_map = {}
    for i, num in enumerate(nums):
        if target - num in num_map:
            return [num_map[target - num], i]
        num_map[num] = i
  • follow up

    • 如果要找三數之和(3Sum)怎麼改?
      • solution
        • 目標是找到所有 nums[i] + nums[j] + nums[k] = 0(或指定 target)的三元組。
        • 標準做法:先排序陣列,固定第一個數,再用雙指針找後兩個數。
        • 時間:O(n²)
        • 空間:O(1)(排序除外)
    fun threeSum(nums: IntArray): List<List<Int>> {
      nums.sort()
      val res = mutableListOf<List<Int>>()
      for (i in nums.indices) {
          if (i > 0 && nums[i] == nums[i - 1]) continue
          var l = i + 1
          var r = nums.size - 1
          while (l < r) {
              val sum = nums[i] + nums[l] + nums[r]
              when {
                  sum < 0 -> l++
                  sum > 0 -> r--
                  else -> {
                      res.add(listOf(nums[i], nums[l], nums[r]))
                      l++
                      r--
                      while (l < r && nums[l] == nums[l - 1]) l++
                      while (l < r && nums[r] == nums[r + 1]) r--
                  }
              }
          }
      }
      return res
    }
    
    • 如果陣列已經排序,怎麼用雙指針解法?
      • solution
        • 如果 nums 已排序,可以用左右指針從頭尾夾逼。
        • 若 sum < target → 左指針右移
        • 若 sum > target → 右指針左移
        • 時間:O(n)
        • 空間:O(1)
    fun twoSumSorted(nums: IntArray, target: Int): IntArray {
      var l = 0
      var r = nums.size - 1
      while (l < r) {
          val sum = nums[l] + nums[r]
          when {
              sum == target -> return intArrayOf(l, r)
              sum < target -> l++
              else -> r--
          }
      }
      return intArrayOf()
    }
    
    • 如果輸入很大,如何降低空間複雜度?
      • 原本 HashMap 解法是 O(n) 空間。
      • 若陣列已排序 → 使用 雙指針,O(1) 空間。
      • 若未排序但空間受限 → 可先排序再雙指針,O(1) 空間但 O(n log n) 時間。
      • 若不能改變原陣列 → 可複製一份排序(O(n) 空間),或用外部排序法處理。
方法 時間複雜度 空間複雜度 適用情況
HashMap O(n) O(n) 未排序且追求 O(n) 時間
雙指針 (排序後) O(n log n) O(1) 可改動陣列
雙指針 (複製排序) O(n log n) O(n) 不能改動原陣列
題型 解法 核心思路 時間複雜度 空間複雜度 Kotlin 範例
Two Sum(未排序) HashMap 儲存 值 -> 索引,邊走邊查 target - nums[i] 是否存在 O(n) O(n) map[target - num] 查找
Two Sum(已排序) 雙指針 左右指針夾逼,如果 sum < target → 左移;sum > target → 右移 O(n) O(1) while(l<r)
Two Sum(空間優化) 排序+雙指針 先排序再雙指針,空間 O(1) 但時間 O(n log n) O(n log n) O(1) 適用空間受限
3Sum 排序+雙指針 固定一數,剩餘用雙指針找目標和 O(n²) O(1) 需跳過重複數
3Sum(指定 target) 排序+雙指針 同 3Sum,只是 target 改成任意值 O(n²) O(1) 可套用到 4Sum

上一篇
#00
系列文
來都來了-涮就涮吧2
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言